/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.hamacekj.geometr.internalplugins;

import cz.hamacekj.geometr.plugin.ConstructionObject;
import cz.hamacekj.geometr.plugin.ConstructionPlugin;
import cz.hamacekj.geometr.plugin.IPoint;
import cz.hamacekj.geometr.plugin.IPointObject;
import cz.hamacekj.geometr.plugin.IRayObject;
import cz.hamacekj.geometr.plugin.IToolBox;
import cz.hamacekj.geometr.plugin.InputParameters;
import cz.hamacekj.geometr.plugin.InputParametersInterface;
import cz.hamacekj.geometr.plugin.ParameterItem;
import cz.hamacekj.geometr.plugin.ParameterObject;
import cz.hamacekj.geometr.plugin.ParameterString;
import cz.hamacekj.geometr.plugin.ParameterValue;
import cz.hamacekj.geometr.plugin.PrimitiveObject;
import cz.hamacekj.geometr.plugin.ValueArgument;
import java.util.HashSet;
import java.util.Set;
import javax.swing.ImageIcon;

/**
 * Plugin pro vytvoření polopřímky.
 * @author hamacekh
 */
public class RayPlugin implements ConstructionPlugin {
    
    protected IToolBox toolbox;
    private String error;
    
    public RayPlugin() {
    }

    public RayPlugin(IToolBox toolbox) {
        this.toolbox = toolbox;
    }
    
    public void setToolbox(IToolBox toolbox) {
        this.toolbox = toolbox;
    }

    @Override
    public String getPluginName() {
        return "Polopřímka";
    }

    @Override
    public InputParametersInterface[] getPossibleParameters() {
        InputParametersInterface twoPoints = new TwoPointsParameters();
        InputParametersInterface[] res = {twoPoints, new ParallelRayParameters(),
        new HalfAngleParameters()};
        return res;
    }

    @Override
    public ImageIcon getIcon() {
        return new ImageIcon("images/poloprimka.png");
    }

    @Override
    public ConstructionObject[] createConstructionObject(InputParametersInterface parametersType, ConstructionObject[] objects, ValueArgument[] values) {
        if(parametersType instanceof TwoPointsParameters){
            final String realName;
            if(values[0].getRealInput().isEmpty()){
                realName = objects[0].getLabel() + objects[1].getLabel();
            }else{
                realName = values[0].getRealInput();
            }

            final IPointObject a = (IPointObject)objects[0].getPrimitiveObjects().iterator().next();
            final IPointObject b = (IPointObject)objects[1].getPrimitiveObjects().iterator().next();

            ConstructionObject obj = new ConstructionObject() {

                @Override
                public String getLabel() {
                    return realName;
                }

                @Override
                public boolean isLabelShown() {
                    return true;
                }

                @Override
                public Set<PrimitiveObject> getPrimitiveObjects() {
                    IRayObject ray = toolbox.createRayObject(a.getPoint(), b.getPoint());
                    HashSet<PrimitiveObject> hs = new HashSet<>(1);
                    hs.add(ray);
                    return hs;
                }

                @Override
                public String getStepDescription() {
                    return "<Polopřímka>"+realName;
                }
            };
            ConstructionObject[] res = {obj};
            return res;
        }
        if(parametersType instanceof ParallelRayParameters){
            final String name = values[0].getRealInput();
            ConstructionObject parallelObject = objects[0];
            IRayObject parallel = (IRayObject)parallelObject.getPrimitiveObjects().iterator().next();
            IPointObject start = (IPointObject)objects[1].getPrimitiveObjects().iterator().next();
            final String parallelName = parallelObject.getLabel();
            final String startName = objects[1].getLabel();
            IPoint A = parallel.getA();
            IPoint B = parallel.getB();
            double vx = B.getX()  - A.getX();
            double vy = B.getY() - A.getY();
            IPoint fst = start.getPoint();
            IPoint snd = toolbox.createPoint(fst.getX() + vx, fst.getY() + vy);
            IRayObject ray = toolbox.createRayObject(fst, snd);
            final Set<PrimitiveObject> set = new HashSet<>();
            set.add(ray);
            ConstructionObject obj = new ConstructionObject() {

                @Override
                public String getLabel() {
                    return name;
                }

                @Override
                public boolean isLabelShown() {
                    return true;
                }

                @Override
                public Set<PrimitiveObject> getPrimitiveObjects() {
                    return set;
                }

                @Override
                public String getStepDescription() {
                    return "<Polopřímka> "+getLabel()+", <Polopřímka> "+parallelName+
                            " <\\parallel> <Polopřímka> "+getLabel();
                }
            };
            ConstructionObject[] res = {obj};
            return res;
        }
        if(parametersType instanceof HalfAngleParameters){
            final String name = values[0].getRealInput();
            if(name.isEmpty()){
                this.error = "Jméno polopřímky nemůže být prázdné";
                return null;
            }
            IPoint first = ((IPointObject)objects[0].getPrimitiveObjects().iterator().next()).getPoint();
            IPoint second = ((IPointObject)objects[2].getPrimitiveObjects().iterator().next()).getPoint();
            IPoint vertex = ((IPointObject)objects[1].getPrimitiveObjects().iterator().next()).getPoint();
            double ux = (first.getX() - vertex.getX())/toolbox.distance(vertex, first);
            double uy = (first.getY() - vertex.getY())/toolbox.distance(vertex, first);
            double vx = (second.getX() - vertex.getX())/toolbox.distance(vertex, second);
            double vy = (second.getY() - vertex.getY())/toolbox.distance(vertex, second);
            double wx = (ux + vx) / 2;
            double wy = (uy + vy) / 2;
            IPoint newPoint = toolbox.createPoint(vertex.getX() + wx*2, vertex.getY() + wy*2);
            if(toolbox.distance(newPoint, vertex) < 0.05){
                this.error = "Nepodařilo se vytvořit osu úhlu. Ramena jsou v rovině.";
                return null;
            }
            IRayObject ray = toolbox.createRayObject(vertex, newPoint);
            Set<PrimitiveObject> set = new HashSet<>();
            set.add(ray);
            ConstructionObject obj = toolbox.createConstructionObject(name, false, set, 
                    "<Polopřímka> "+name+", <Polopřímka> "+name+" je osa <Úhel>"+first+second+vertex);
            ConstructionObject[] res = { obj };
            return res;
        }
        return null;
    }
    
    @Override
    public String getError(){
        return error;
    }
    
    private class TwoPointsParameters extends InputParameters {

        @Override
        public String getParametersCaption() {
            return "Dva body";
        }

        @Override
        public ParameterItem[] getParameters() {
            ParameterItem[] res = new ParameterItem[4];
            res[0] = new ParameterString() {

                @Override
                public String getText() {
                    return "Název";
                }
            };
            res[1] = new ParameterValue() {

                @Override
                public String getCaption() {
                    return "Název";
                }
            };
            res[2] = new ParameterObject() {

                @Override
                public String getCaption() {
                    return "První bod";
                }

                @Override
                public String[] getObjectNames() {
                    String[] res = {"Bod"};
                    return res;
                }
            };
            res[3] = new ParameterObject() {

                @Override
                public String getCaption() {
                    return "Druhý bod";
                }

                @Override
                public String[] getObjectNames() {
                    String[] res = {"Bod"};
                    return res;
                }
            };
            return res;
        }

    }
    
    private class ParallelRayParameters extends InputParameters{

        @Override
        public String getParametersCaption() {
            return "Rovnoběžná polopřímka, bod";
        }

        @Override
        public ParameterItem[] getParameters() {
            ParameterItem[] res = new ParameterItem[6];
            res[0] = new ParameterString() {

                @Override
                public String getText() {
                    return "Název";
                }
            };
            res[1] = new ParameterValue() {

                @Override
                public String getCaption() {
                    return "Název";
                }
            };
            res[2] = new ParameterString() {

                @Override
                public String getText() {
                    return "Rovnoběžná polopřímka";
                }
            };
            res[3] = new ParameterObject() {

                @Override
                public String getCaption() {
                    return "Polopřímka";
                }

                @Override
                public String[] getObjectNames() {
                    String[] res = { "Polopřímka" };
                    return res;
                }
            };
            res[4] = new ParameterString() {

                @Override
                public String getText() {
                    return "Počáteční bod";
                }
            };
            res[5] = new ParameterObject() {

                @Override
                public String getCaption() {
                    return "Bod";
                }

                @Override
                public String[] getObjectNames() {
                    String[] res = { "Bod" };
                    return res;
                }
            };
            return res;
        }

        @Override
        public String getHelp() {
            return "<h1>Rovnoběžná polopřímka, bod</h1>"
                    + "<p>Tato možnost slouží k vytvoření polopřímky s názvem v "
                    + "parametru <b>Název</b> rovnoběžné k polopřímce "
                    + "v parametru <b>Polopřímka</b>. Nová polopřímka bude mít "
                    + "stejnou orientaci jako ta rovnoběžná a její počáteční bod je určen "
                    + "parametrem <b>Bod</b>.</p>";
        }
        
    }
    
    private class HalfAngleParameters extends InputParameters {

        @Override
        public String getParametersCaption() {
            return "Osa úhlu";
        }

        @Override
        public ParameterItem[] getParameters() {
            ParameterItem[] res = new ParameterItem[6];
            res[0] = new ParameterString() {

                @Override
                public String getText() {
                    return "Název";
                }
            };
            res[1] = new ParameterValue() {

                @Override
                public String getCaption() {
                    return "Název";
                }
            };
            res[2] = new ParameterString() {

                @Override
                public String getText() {
                    return "Body úhlu";
                }
            };
            res[3] = new ParameterObject() {

                @Override
                public String getCaption() {
                    return "1. bod";
                }

                @Override
                public String[] getObjectNames() {
                    String[] res = { "Bod" };
                    return res;
                }
            };
            res[4] = new ParameterObject() {

                @Override
                public String getCaption() {
                    return "Vrchol";
                }

                @Override
                public String[] getObjectNames() {
                    String[] res = { "Bod" };
                    return res;
                }
            };
            res[5] = new ParameterObject() {

                @Override
                public String getCaption() {
                    return "2. bod";
                }

                @Override
                public String[] getObjectNames() {
                    String[] res = { "Bod" };
                    return res;
                }
            };
            return res;
        }
        
    }
    
}
